/* eslint-disable import/no-cycle */
import AsyncStorage from '@react-native-community/async-storage';
import protobufjs from 'protobufjs';

import {
  STORAGE_KEY_USER_INFO,
  APP_NAME,
  APP_VERSION,
  CHANNEL,
  DEVICE_ID,
  OS_TYPE
} from '../constant';
import { setHeaderToken } from '../service/ShellExec';
import userTable, { USER_DB_USER_INFO } from '../service/userTable';
import { RowData } from '../common/db';
import inAppPurchaseModule from '../util/native/inAppPurchaseModule';
import { constant, shellExec } from '../util/native';
import connection from '../service/connection';
import { UserRole } from '../pages/ClassRoom/constant';

export interface User {
  userId?: string;
  token?: string;
  isGuest?: boolean;
  nickName?: string;
  role?: UserRole;
  headUrl?: string;
  currentGrade?: number;
}

export interface UserInfo {
  userId: string; // 用户id
  token: string; // 登录token
  isGuest: boolean;
  nickName: string;
  role?: UserRole;
  headUrl: string;
  currentGrade?: number;
}

let userId = '0';
let token = '';
let isGuest = false;
let nickName = '';
let role = UserRole.Student;
let headUrl = '';
let currentGrade = 0;

const updateUserInfo = (): void => {
  if (token !== '') {
    setHeaderToken(token);

    const clientInfo = {
      userId,
      appName: APP_NAME,
      appVersion: APP_VERSION,
      channelName: CHANNEL,
      deviceId: DEVICE_ID,
      platInfo: OS_TYPE
    };

    constant.putString('token', token, 'USER_INFO');
    constant.putString('clientInfo', JSON.stringify(clientInfo), 'USER_INFO');
  }
  const root = protobufjs.Root.fromJSON(connection);
  if (root) {
    const Message = root.lookupType('client.CPacketIdentifyLongLinkReq');
    const message = Message.create({ userId: Number(userId) });
    const messageBuffer = Message.encode(message).finish();
    const messageArray = Array.from(messageBuffer);

    if (Number(userId) === 0) {
      constant.putString('identifyLongLink', '', 'USER_INFO');
      return;
    }

    constant.putString(
      'identifyLongLink',
      messageArray.toString(),
      'USER_INFO'
    );
  }
};

export const initUserInfo = (): Promise<void> => {
  return new Promise((resolve): void => {
    AsyncStorage.getItem(STORAGE_KEY_USER_INFO).then((res: any): void => {
      if (res) {
        const info = JSON.parse(res);
        ({ userId } = info);

        inAppPurchaseModule.startTransactionObservingAndPaymentTransactionVerifingWithUserID(
          userId
        );

        userTable
          .connect(userId)
          .then((): void => {
            userTable
              .load(USER_DB_USER_INFO)
              .then((data: RowData[]): void => {
                if (data.length > 0) {
                  const user = JSON.parse(data[data.length - 1].content);
                  userId = user.userId || '0';
                  token = user.token || '';
                  isGuest = user.isGuest || false;
                  nickName = user.nickName || '';
                  role = user.role || UserRole.Student;
                  headUrl = user.headUrl || '';
                  currentGrade = user.currentGrade || 0;
                  updateUserInfo();
                } else {
                  AsyncStorage.removeItem(STORAGE_KEY_USER_INFO);
                  userTable.disconnect();
                }
                resolve();
              })
              .catch(resolve);
          })
          .catch(resolve);
      } else {
        updateUserInfo(); // 没有用户记录也走实名化
        resolve();
      }
    });
  });
};

export const setUserInfo = ({
  userId: localUserId = userId,
  token: localToken = token,
  isGuest: localIsGuest = isGuest,
  nickName: localNickName = nickName,
  role: localRole = role,
  headUrl: localHeadUrl = headUrl,
  currentGrade: localCurrentGrade = currentGrade
}: User): void => {
  const info = JSON.stringify({
    userId: localUserId,
    token: localToken,
    isGuest: localIsGuest,
    nickName: localNickName,
    role: localRole,
    headUrl: localHeadUrl,
    currentGrade: localCurrentGrade
  });

  userId = localUserId;
  token = localToken;
  isGuest = localIsGuest;
  nickName = localNickName;
  role = localRole;
  headUrl = localHeadUrl;
  currentGrade = localCurrentGrade;

  updateUserInfo();

  AsyncStorage.setItem(
    STORAGE_KEY_USER_INFO,
    JSON.stringify({
      userId: localUserId
    })
  );

  if (userTable.getConnectStatus()) {
    userTable.replace(USER_DB_USER_INFO, { content: info, uid: userId });
  } else {
    userTable.connect(localUserId).then((): void => {
      userTable.replace(USER_DB_USER_INFO, {
        content: info,
        uid: userId
      });
    });
  }
};

export const getUserInfo = (): UserInfo => {
  return {
    userId,
    token,
    isGuest,
    nickName,
    role,
    headUrl,
    currentGrade
  };
};

export const clearIdentifyInfo = (): void => {
  const root = protobufjs.Root.fromJSON(connection);
  if (root) {
    constant.putString('identifyLongLink', '', 'USER_INFO');
  }
};

export const clearUserInfo = (): void => {
  userId = '0';
  token = '';
  isGuest = false;
  nickName = '';
  role = UserRole.Student;
  headUrl = '';
  currentGrade = 0;
  AsyncStorage.removeItem(STORAGE_KEY_USER_INFO);
  userTable.disconnect();
  inAppPurchaseModule.logoutPaymentManager();
  shellExec.clearTask();
  clearIdentifyInfo();
  shellExec.destroyMars();
};
